import {
  reactive
} from './reactive';
import {
  isObject
} from './utils';
import {
  compileAttr
} from './compile';

class Vue {
  constructor(options) {
    const {
      el,
      data,
      template
    } = options;

    this.$data = data();
    this.$el = document.querySelector(el);
    this.$stylePool = new Map();

    this.init(this, template);
  }

  init(vm, temlate) {
    this.initData(vm);
    this.render(vm, temlate);

    /**
     * console.log(vm.$stylePool):
     * Map(4) {
     *   {div.box.show.danger => {type: "class", expression: "['box',isShow?'show':'',hasError?'danger':'']"}}, 
     *   {h1 => {type: "style", expression: "[titleStyle,{display:titleShow?'block':'none'}]"}}, 
     *   {h2 => {type: "style", expression: "{display:titleShow?'block':'none',color:subTitleColor,fontSize:'20px'}"}}, 
     *   {p.danger.big => {type: "class", expression: "{danger:hasError,big:isContentBig}"}}
     * }
     */

  }

  render(vm, template) {
    const container = document.createElement('div');
    //将字符串模板转为dom节点的模板
    container.innerHTML = template;
    // console.log(container);

    /**
     * <div>
     *   <div :class="[...]">
     *     <h1 :style="[...]">This is Title</h1>
     *     <h2 :style="{...}">This is Sub_Title</h2>
     *     <p :class="{...}">This is Content</p>
     *   </div>
     * </div>
     */

    //解析style/class
    this.compileAttrs(vm, container);
    this.$el.appendChild(container);
  }

  initData(vm) {
    const _data = vm.$data;

    if (isObject(_data)) {
      reactive(vm, _data);
    }
  }

  /**
   * 解析style/class字符串
   * @param {object} vm 实例对象
   * @param {HTMLDivElement} container 带有模板dom节点
   */
  compileAttrs(vm, container) {
    //将container底下所有的dom节点都平铺到数组里面
    const allNodes = [...container.getElementsByTagName('*')];
    // console.log(allNodes);
    //[div, h1, h2, p]

    //枚举每一个元素节点
    allNodes.forEach(el => {
      //拿到每一元素节点的标签属性平铺到数组里面
      const attrs = [...el.attributes];
      attrs.forEach(attr => {
        const {
          name,
          value
        } = attr;

        // console.log(name); :class
        // console.log(value);
        //['box', isShow ? 'show' : '', hasError ? 'danger' : '']

        //编译
        compileAttr(vm, el, name, value);
      });

      //移除节点上的标签属性
      el.removeAttribute(':class');
      el.removeAttribute(':style');
    })
  }

}

export default Vue;